package com.irdstudio.efp.esb.service.client;

import static java.util.Objects.requireNonNull;

import com.irdstudio.efp.esb.service.client.impl.DefaultESBBeanCreator;
import com.irdstudio.efp.esb.service.client.impl.DefaultESBConfig;
import com.irdstudio.efp.esb.service.client.impl.ESBClient;
import com.irdstudio.efp.esb.service.client.impl.ESBClientImpl;
import com.irdstudio.basic.framework.core.util.SpringContextUtils;

/**
 * @description:创建ESB客户端以发送接口
 * 				调用例子:
 *					<p>SomeBean bean = ESBClientFactory
 *			 						<p>.buildClient()
 *			 						<p>.withBody(your-body-bean)
 *			 						<p>.withTradeNo(your-trade-no)
 *									<p>. (some other parameters...)
 *			 						<p>.create()
 *			 						<p>.sendAndReceive()
 *			 						<p>.getBody(SomeBean.class);<p>
 * 说明：其中your-body-bean为你要发送的接口请求bean，见 QueryReport;
 * your-trade-no为你要发送的接口ID;
 * SomeBean为你要接收的接口响应报文bean。
 * getBody具体用法见：EsbRespServiceBean
 *
 * @see ESBClient
 * @see com.irdstudio.efp.esb.common.client.resp.EsbRespServiceBean
 * @date:2018年12月18日 上午10:01:48
 * @author:hengyh
 */
public class ESBClientFactory {
	/* 
	 * FIXME 其实这个类名并不恰当，应为ESBRequestBuilder，这里应该用于
	 产生一个ESBRequest对象，只需传入Body、tradeNo、scene三个参数构建即可
	 ESBClientImpl应是单例的
	 */

	public static Builder  buildClient() {
		return new Builder();
	}
	
	public static class Builder {
		/* MUST NOT NULL */
		private Object bodyBean;
		private String tradeNo;
		private String scene;
		private String msgTp;
		
		/* OPTIONAL */
		// default ESB's config is DefaultESBConfig
		private ESBConfig config = SpringContextUtils.getBean(DefaultESBConfig.class);
		private HttpClientFactory factory = SimpleHttpClientFactory.newInstance(config.getTimeout());
		private ESBBeanCreator esbBeanCreator = DefaultESBBeanCreator.getINSTANCE();
		
		/* 
		 * build methods 
		 * */
		public Builder withBody(Object object) 
			{ bodyBean = requireNonNull(object); return this; }
		public Builder withTradeNo(String tradeNo)
			{ this.tradeNo = requireNonNull(tradeNo); return this; }
		public Builder withMsgTp(String msgTp){
			this.msgTp = requireNonNull(msgTp);
			return this;
		}
		public Builder withScene(String scene)
			{ this.scene = requireNonNull(scene); return this; }
		public Builder withConfig(ESBConfig config)
			{ this.config = requireNonNull(config); return this; }
		public Builder withHttpClientFactory(HttpClientFactory factory)
			{ this.factory = requireNonNull(factory); return this; }
		public Builder withESBBeanFactory(ESBBeanCreator esbBeanCreator)
			{ this.esbBeanCreator = requireNonNull(esbBeanCreator); return this; }
		public ESBClient create() {
			return new ESBClientImpl(this);
		}
		
		/* 
		 * getters
		 * */
		public Object getToSend() { return bodyBean; }
		public String getTradeNo() { return tradeNo; }
		public String getScene() { return scene; }
		public ESBConfig getConfig() { return config; }
		public ESBBeanCreator getESBBeanFactory() { return esbBeanCreator; }
		public HttpClientFactory getFactory() { return factory; }

		public String getMsgTp() {
			return msgTp;
		}
	}
	
	private ESBClientFactory() { throw new IllegalAccessError(); }
}
